﻿using Algorithm.Check;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using static Algorithm.Check.ExtensionForCRC16;
using static System.Runtime.InteropServices.JavaScript.JSType;

#pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider adding the 'required' modifier or declaring as nullable.

// ReSharper disable PrivateFieldCanBeConvertedToLocalVariable
// ReSharper disable CollectionNeverQueried.Local

namespace NewDevice.RS485
{
    /// <summary>
    /// 奇嘉信4路PWM发生器
    /// </summary>
    public class QjxPwm4
    {
        private readonly OldSerialBase _serial;
        private readonly int _slaveId;
        private readonly string _deviceName;
        private ChannelHexConverter hexConverter;

        /// <summary>
        /// 周期频率，单位hz
        /// </summary>
        private double _freunency;

        /// <summary>
        /// 毫秒单位方波
        /// </summary>
        private double _periodMs;

        public QjxPwm4(OldSerialBase bus, int slaveId, double freunency = 1000, string name = "PWM方波输出模块")
        {
            _freunency = freunency;
            //hz转化成周期多少毫秒的方波
            _periodMs = (1.0 / freunency) * 1000;
            _serial = bus;
            this._slaveId = slaveId;
            this._deviceName = name;
            hexConverter = new ChannelHexConverter();
        }

        /// <summary>
        /// 设置默认频率，单位HZ
        /// </summary>
        public void SetDeFaultFreunency(double value)
        {
            _freunency = value;
            //hz转化成周期多少毫秒的方波
            _periodMs = (1.0 / value) * 1000;
        }

        /// <summary>
        /// 读取默认频率，单位HZ
        /// </summary>
        public double GetDeFaultFreunency()
        {
            return this._freunency;
        }

        /// <summary>
        /// 单独输出一路PWM,高电平时间(占空比)
        /// </summary>
        public void SetOneStation(int index, int value)
        {
            if (value < 0 || value > 100)
            {
                return;
            }
            byte[] data = [
                (byte)_slaveId,
                0x10
            ];
            byte[] dataSecond = [
                0x00,
                0x04,
                0x08
            ];
            //占空比转化成实际输出高电平时间
            int frequency = (int)(_periodMs * 1000000);//周期时间
            int highTiem = (int)(_periodMs * value * 10000);//高电平时间

            byte[] frequencyByte = byteConver(frequency);
            byte[] highTiemByte = byteConver(highTiem);
            byte[] stationByte = ChannelHexConverter.GetBytesForChannel4(index);
            byte[] mergedArray = data.Concat(stationByte).ToArray();
            byte[] mergedArray2 = mergedArray.Concat(dataSecond).ToArray();
            byte[] mergedArray3 = mergedArray2.Concat(highTiemByte).ToArray();
            byte[] mergedArray4 = mergedArray3.Concat(frequencyByte).ToArray();
            byte[] cmd = mergedArray4.WithCRC16(CRC16Type.Modbus).ToArray();
            _serial.deviceName = _deviceName;
            var recv = _serial.SendBytesAndWaitResponse(cmd, ReceivedDataCheck.FuncModbusCRC16Check);
        }

        /// <summary>
        /// 设置全工位输出状态以及占空比，使用默认赫兹
        /// </summary>
        public void SetALLStation(int value)
        {
            if (value < 0 || value > 100)
            {
                return;
            }
            byte[] data = [
                (byte)_slaveId,
                0x10,
                0x01,
                0x50,
                0x00,
                0x10,
                0x20
            ];
            //占空比转化成实际输出高电平时间
            int frequency = (int)(_periodMs * 1000000);//周期时间
            int highTiem = (int)(_periodMs * value * 10000);//高电平时间
            byte[] frequencyByte = byteConver(frequency);
            byte[] highTiemByte = byteConver(highTiem);
            byte[] mergedArray1 = data.Concat(highTiemByte).ToArray();
            byte[] mergedArray2 = mergedArray1.Concat(frequencyByte).ToArray();
            byte[] mergedArray3 = mergedArray2.Concat(highTiemByte).ToArray();
            byte[] mergedArray4 = mergedArray3.Concat(frequencyByte).ToArray();
            byte[] mergedArray5 = mergedArray4.Concat(highTiemByte).ToArray();
            byte[] mergedArray6 = mergedArray5.Concat(frequencyByte).ToArray();
            byte[] mergedArray7 = mergedArray6.Concat(highTiemByte).ToArray();
            byte[] mergedArray8 = mergedArray7.Concat(frequencyByte).ToArray();
            byte[] cmd = mergedArray8.WithCRC16(CRC16Type.Modbus).ToArray();
            _serial.deviceName = _deviceName;
            var recv = _serial.SendBytesAndWaitResponse(cmd, ReceivedDataCheck.FuncModbusCRC16Check);
        }

        public byte[] byteConver(int value)
        {
            byte[] bytes = BitConverter.GetBytes(value);
            // 转换为大端序（如果系统是小端序）
            if (BitConverter.IsLittleEndian)
            {
                Array.Reverse(bytes);
            }

            return bytes;
        }

        /// <summary>
        /// 关闭
        /// </summary>
        public void Close()
        {
            _serial.Close();
        }

        /// <summary>
        /// 字节转化
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        private byte[] ConvertToCustomBytes(int value)
        {
            byte[] bytes = new byte[4];
            bytes[0] = (byte)(value >> 24); // 第 4 字节 (00)
            bytes[1] = (byte)(value >> 16);  // 第 3 字节 (00)
            bytes[2] = (byte)(value >> 8);  // 第 2 字节 (02)
            bytes[3] = (byte)(value & 0xFF); // 第 1 字节 (52)

            //bytes[0] = (byte)(value >> 8); // 第 4 字节 (00)
            //bytes[1] = (byte)(value & 0xFF); // 第 3 字节 (00)
            //bytes[2] = (byte)(value >> 24);  // 第 2 字节 (02)
            //bytes[3] = (byte)(value >> 16); // 第 1 字节 (52)
            return bytes;
        }
    }

    public class ChannelHexConverter
    {
        // 存储通道号与对应字节数组的字典
        private static Dictionary<int, byte[]> _channelToHexMap;

        public ChannelHexConverter()
        {
            _channelToHexMap = new Dictionary<int, byte[]>();

            // 初始化30个通道的映射（通道0~29）
            for (int channel = 0; channel < 30; channel++)
            {
                // 计算当前通道的十六进制值（05 DE + channel）
                ushort hexValue = (ushort)(0x05DE + channel);

                // 将ushort转换为2字节数组（大端序）
                byte[] bytes = new byte[]
                {
                    (byte)(hexValue >> 8),  // 高位字节（如0x05）
                    (byte)(hexValue & 0xFF) // 低位字节（如0xDE）
                };

                _channelToHexMap.Add(channel, bytes);
            }
        }

        // 根据通道号获取对应的字节数组16路
        public static byte[] GetBytesForChannel4(int channel)
        {
            switch (channel)
            {
                case 1:
                    return [0x01, 0x50];

                case 2:
                    return [0x01, 0x56];

                case 3:
                    return [0x01, 0x5C];

                case 4:
                    return [0x01, 0x62];

                default:
                    return [0x01, 0x50];
            }
        }

        public static byte[] GetBytesForChannel16(int channel)
        {
            switch (channel)
            {
                case 1:
                    return [0x01, 0x50];

                case 2:
                    return [0x01, 0x56];

                case 3:
                    return [0x01, 0x5C];

                case 4:
                    return [0x01, 0x62];

                case 5:
                    return [0x01, 0x68];

                case 6:
                    return [0x01, 0x6E];

                case 7:
                    return [0x01, 0x74];

                case 8:
                    return [0x01, 0x7A];

                case 11:
                    return [0x01, 0x20];

                case 12:
                    return [0x01, 0x26];

                case 13:
                    return [0x01, 0x2C];

                case 14:
                    return [0x01, 0x32];

                case 21:
                    return [0x01, 0x38];

                case 22:
                    return [0x01, 0x3E];

                case 23:
                    return [0x01, 0x44];

                case 24:
                    return [0x01, 0x4A];

                default:
                    return [0x01, 0x50];
            }
        }
    }
}